跳到主要內容

Pub 工作區 (monorepo 支援)

在專案開發中,您可能會在同一個版本控制儲存庫 (monorepo) 中開發多個 Dart 套件。

例如,您可能會有如下的目錄佈局

/
  packages/
    shared/
      pubspec.yaml
      pubspec.lock
      .dart_tool/package_config.json
    client_package/
      pubspec.yaml
      pubspec.lock
      .dart_tool/package_config.json
    server_package/
      pubspec.yaml
      pubspec.lock
      .dart_tool/package_config.json

這種設定方式有一些缺點

  • 您需要為每個套件執行一次 dart pub get
  • 您可能會遇到每個套件的依賴項版本不同的風險,這會在套件之間切換上下文時造成混淆。
  • 如果您在 IDE 中開啟根資料夾,dart 分析器會為每個套件建立獨立的分析上下文,進而增加記憶體使用量。

Pub 允許您使用單一共享解析度來組織儲存庫為工作區,以供所有套件使用。對於大型儲存庫,使用工作區可以減少分析所需的記憶體量,進而提升效能。

建立工作區的步驟

  • 在儲存庫根目錄中新增一個 pubspec.yaml 檔案,並加入 workspace 條目,列舉儲存庫中套件的路徑 (工作區套件)

    yaml
    name: _
    publish_to: none
    environment:
      sdk: ^3.6.0
    workspace:
      - packages/helper
      - packages/client_package
      - packages/server_package
  • 針對每個現有的 pubspec.yaml 檔案,請確保其 SDK 約束至少為 ^3.6.0,並加入 resolution 條目

    yaml
    environment:
      sdk: ^3.6.0
    resolution: workspace
  • 在儲存庫中的任何位置執行 dart pub get。這將會

    • 在根 pubspec.yaml 檔案旁邊建立一個單一的 pubspec.lock 檔案,其中包含所有工作區套件的所有 dependenciesdev_dependencies 的解析結果。
    • 建立一個單一共享的 .dart_tool/package_config.json 檔案,將套件名稱對應到檔案位置。
    • 刪除工作區套件旁邊任何其他現有的 pubspec.lock.dart_tool/package_config.json 檔案。

現在檔案結構看起來像這樣

/
  packages/
    shared/
      pubspec.yaml
    client_package/
      pubspec.yaml
    server_package/
      pubspec.yaml
  pubspec.yaml
  pubspec.lock
  .dart_tool/package_config.json

散佚檔案

#

當您遷移現有的 monorepo 以使用 Pub 工作區時,每個 pubspec 旁邊都會有現有的「散佚」 pubspec.lock.dart_tool/package_config.json 檔案。這些檔案會遮蔽放置在根目錄旁邊的 pubspec.lock.dart_tool/package_config.json 檔案。

因此,pub get 將會刪除位於根目錄和 (包含) 任何工作區套件之間目錄中的任何 pubspec.lock.dart_tool/package_config.json 檔案。

/
  pubspec.yaml                       # Root
  packages/
    pubspec.lock                     # Deleted by `pub get`
    .dart_tool/package_config.json   # Deleted by `pub get`
    foo/
      pubspec.yaml                   # Workspace member
      pubspec.lock                   # Deleted by `pub get`
      .dart_tool/package_config.json # Deleted by `pub get`

如果工作區根目錄和工作區套件之間的任何目錄包含不屬於工作區成員的「散佚」 pubspec.yaml 檔案,pub get 將會報告錯誤並解析失敗。這是因為解析這樣的 pubspec.yaml 檔案會建立一個 .dart_tool/package_config.json 檔案,而該檔案會遮蔽根目錄中的檔案。

例如

/
  pubspec.yaml                      # Root `workspace: ['foo/']`
  packages/
    pubspec.yaml                    # Not workspace member => error
    foo/
      pubspec.yaml                  # Workspace member

工作區套件之間的相互依賴性

#

如果任何工作區套件彼此依賴,它們將自動解析為工作區中的套件,無論來源為何。

例如,packages/client_package/pubspec.yaml 可能依賴 shared

yaml
dependencies:
  shared: ^2.3.0

當在工作區內解析時,將會使用 shared本機版本。

不過,shared 的本機版本仍然必須符合約束 (^2.3.0)。

但是,當套件作為依賴項被使用,且不屬於工作區的一部分時,將會使用原始來源 (此處隱含為 hosted)。

因此,如果 client_package 發佈到 pub.dev 且有人依賴它,他們將會取得 shared 的 hosted 版本作為傳遞依賴項。

工作區中的依賴項覆寫

#

工作區套件中的所有 dependency_overrides 區段都會被遵循。您也可以將 pubspec_overrides.yaml 檔案放在任何工作區 pubspec.yaml 檔案旁邊。

您在工作區中只能覆寫一個套件一次。為了保持覆寫的組織性,最好將 dependency_overrides 保留在根 pubspec.yaml 檔案中。

在特定的工作區套件中執行命令

#

某些 pub 命令,例如 dart pub adddart pub publish,會對「目前」套件進行操作。您可以變更目錄,或使用 -C 將 pub 指向目錄

$ dart pub -C packages/client_package publish
# Same as
$ cd packages/client_package ; dart pub publish ; cd -

暫時解析工作區外的套件

#

有時您可能想要單獨解析工作區套件,例如驗證其依賴項約束。

一種方法是建立一個 pubspec_overrides.yaml 檔案,以重設 resolution 設定,如下所示

yaml
# packages/client_package/pubspec_overrides.yaml
resolution:

現在在 packages/client_package 內執行 dart pub get 將會建立一個獨立的解析。

列出所有工作區套件

#

您可以執行 dart pub workspace list 以列出工作區的套件。

$ dart pub workspace list
Package         Path                      
_               ./                        
client_package  packages/client_package/  
server_package  packages/server_package/  
shared          packages/shared/